require("luci.tools.webadmin")

local ds =  require "luci.dispatcher"
local sys = require "luci.sys"
local fs  = require "nixio.fs"

 


local m, s, o, tmpl
local op






--[[
	@brief 将传入的字符串使用指定的分隔符分割，并放入到table中
	@param s 目标字符串
	@param reps 要分割的串
--]]
function rsplit(str, reps)
    local resultStrsList = {};
    if str == nil then
      return resultStrsList;
    end
    if type(str) ~= "string" then
		return {}	
	end
    string.gsub(str, '[^' .. reps ..']+', function(w) table.insert(resultStrsList, w) end );
    return resultStrsList;
end

--[[
	@brief 去除字符串中所有空格
	@param s 字符串
--]]
function trim (s) 
  return (string.gsub(s, "%s*(.-)%s*", "%1")) 
end 

function chk_ip4addr(tb)
		local tmp_tb={}
		table.foreach(tb, function(i, v)
			if luci.ip.IPv4(v) then
				table.insert(tmp_tb,v)
			end
		end)
        return tmp_tb
end

--[[
	@brief  Portal配置选项
	@param s section指针
	@param tname s渲染的taboption名称 
--]]
function render_portal( s , tname)
	o = s:taboption(tname, ListValue, "t_flag", translate("push the portal page"))
	o.default = "0"
	o:value("1", translate("off"))
	o:value("0", translate("on"))
	function o.cfgvalue(...)
		return m.uci:get("nac", "portal_cfg", "flag")                            
	end               
	function o.write(self, section, value)
	    m.uci:set("nac", "portal_cfg", "flag", value)
	end

	-- @option nac.portal_cfg.check_interval
	o = s:taboption(tname, Value, "p_check_interval", translate("IdelTime")
		,translate("Idle users cut off time, the unit is' second ', the maximum can not exceed 24 hours, that is, 86400 seconds"))
	o.datatype= "max(86400)"
	function o.cfgvalue(...)
		return m.uci:get("nac", "NAC", "check_interval")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "portal_cfg", "check_interval", value)
	end

--[[
	-- @option nac.portal_cfg.pre_sesstime
	o = s:taboption(tname, Value, "p_pre_sesstime", translate("Pre-Free Session Time"),translate("0 - 600 seconds ,0 is disabled"))

	 o.datatype= "and(min(0),max(600)"
	function o.cfgvalue(...)
		return m.uci:get("nac", "portal_cfg", "pre_sesstime")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "portal_cfg", "pre_sesstime", value)
	end
]]--
 	o = s:taboption(tname,Value,"special_ip",translate("Special IP"),translate("Push portal when target is this IP"))
 	o:depends("t_flag",0)
 	o.datatype = "ip4addr"
 	o.default="3.3.3.3"





--o = s:taboption(tname, File, "test", translate("Test"))

o = s:taboption(tname, Value, "primary_server", translate("Primary Portal Server")
		,translate("NAC will synchronize portal's page from this server"))
--o.template = "cbi/value"
o.size  =  1024
--o.maxlength = 1024
	o.datatype= "and(minlength(1),maxlength(1024))"
	o:depends("t_prt_type", "3")
	function o.cfgvalue(...)
		return m.uci:get("nac", "portal_cfg", "primary_server")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "portal_cfg", "primary_server", value)
	end


o = s:taboption(tname, Value, "secondary_server", translate("Secondary Portal Server")
		,translate("NAC will synchronize portal's page from this server"))
o.template = "cbi/value"
	o.datatype= "and(minlength(1),maxlength(1024))"
		o:depends("t_prt_type", "3")
	function o.cfgvalue(...)
		return m.uci:get("nac", "portal_cfg", "secondary_server")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "portal_cfg", "secondary_server", value)
	end




end




function render_macauth(s,tname)
	-- @option nac.radius_cfg.mac_addr
	o = s:taboption(tname, DynamicList, "mac_auth", translate("MAC-Address"),translate("MAC-Address(e.g. xx:xx:xx:xx:xx)"))
	o.datatype = "macaddr"
 
	function o.cfgvalue(...)
		return m.uci:get("nac", "radius_cfg", "mac_addr")
	end

	function o.write(self, section, value)
		m.uci:set("nac", "radius_cfg", "mac_addr", value)
		
	end

end



function render_radius( s, tname )

	-- @option nac.radius_cfg.server
	o = s:taboption(tname, Value, "r_server", translate("Radius server IP"),translate("Radius server IP address"))
	o.datatype = "ip4addr"

	function o.cfgvalue(...)
		return m.uci:get("nac", "radius_cfg", "server")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "radius_cfg", "server", value)
		
	end

	o=s:taboption(tname, ListValue, "radius_mode", translate("Radius mode"))                                                                                                          
	o.default = 0               

	o:value(1, translate("Production"))                                                                                                                                  
	o:value(0, translate("Test")) 
        function o.cfgvalue(...)                                                                                                                                                               
                return m.uci:get("nac", "radius_cfg", "radius_mode")                                                                                                                                
        end                                                                                                                                                                                    
        function o.write(self, section, value)                                                                                                                                                 
                m.uci:set("nac", "radius_cfg", "radius_mode", value)     
                if(value == "1" ) then
                	m.uci:set("nac", "radius_cfg", "auth_port", "9812") 
                	m.uci:set("nac", "radius_cfg", "acount_port", "9813") 
                end                         
                if(value == "0" ) then
                	m.uci:set("nac", "radius_cfg", "auth_port", "8812") 
                	m.uci:set("nac", "radius_cfg", "acount_port", "8813") 
                end                                                                                                    
        end





	-- @option nac.radius_cfg.check_interval
	o = s:taboption(tname, Value, "r_acct_time", translate("Billing cycle"),translate("If you fill in 120 seconds, said every 120 seconds to send an update to the accounting message, the unit is' second '"))
	o.datatype= "max(3600)"
	function o.cfgvalue(...)
		return m.uci:get("nac", "radius_cfg", "acct_time")
	end
	function o.write(self, section, value)
		m.uci:set("nac", "radius_cfg", "acct_time", value)
	end

	-- @option nac.radius_cfg.acct_op



end

--[[
	@brief  目的IP bypass配置选项
	@param s section指针
	@param tname s渲染的taboption名称 
--]]
function render_bypass_outer_free( s, tname )
	dstip = s:taboption(tname, Value, "b_outer", translate("Destination IP address List"),translate("Each line of an IP address, the format is 10.10.10.10"))
	dstip.template = "cbi/tvalue"
	dstip.rows = 5
	function dstip.cfgvalue(self, section)
		local fd = io.open("/etc/config/freeDstip", "r")
		local str = ""
		if fd then
			str = fd:read("*a")
			fd:close()
		else
			fd = io.open("/etc/config/freeDstip", "w")
			if fd then
				fd:close()
				fd = io.open("/etc/config/freeDstip", "r")
				if fd then
					str = fd:read("*a")
					fd:close()
				end
			end
		end
		return str
	end
	function dstip.write(self, section, value)
		--替换换行为\n
		value = value:gsub("\r\n?", "\n")
		local tb
		--移除所有空格
		tb=trim(value)
		local fd = io.open("/etc/config/freeDstip", "w")
		if string.len(tb) > 0 then
			local str = ""
			tb = rsplit(value,"\n")
			-- 过滤掉非IPV4地址
			tb = chk_ip4addr(tb)
			if next(tb) then
				for i,v in ipairs(tb) do
					str = str .. v .. "\n"
				end
				if fd then
					fd:write(str)
					fd:close()
				end
				-- --需要判断IP是否正确
				-- m.uci:set("nac", "bypass", "inter", tb)
			else
				-- m.uci:delete("nac", "bypass", "inter")
				if fd then fd:close() end
			end
		else
			if fd then fd:close() end
			--m.uci:delete("nac", "bypass", "inter")
		end
		m.uci:commit("nac")
	end

end

-- 内网白名单
function render_bypass_inter_free(s,tname)
	-- 内网IP白名单
	srcip = s:taboption(tname, Value, "b_inter", translate("Source IP address List"),translate("Each line of an IP address, the format is 10.10.10.10"))
	srcip.template = "cbi/tvalue"
	srcip.rows = 5
	function srcip.cfgvalue(self, section)
		local fd = io.open("/etc/config/freeSrcip", "r")
		local str = ""
		if fd then
			str = fd:read("*a")
			fd:close()
		else
			fd = io.open("/etc/config/freeSrcip", "w")
			if fd then
				fd:close()
				fd = io.open("/etc/config/freeSrcip", "r")
				if fd then
					str = fd:read("*a")
					fd:close()
				end
			end
		end
		return str
	end
	function srcip.write(self, section, value)
		--替换换行为\n
		value = value:gsub("\r\n?", "\n")
		local tb
		--移除所有空格
		tb=trim(value)
		local fd = io.open("/etc/config/freeSrcip", "w")
		if string.len(tb) > 0 then
			local str = ""
			tb = rsplit(value,"\n")
			-- 过滤掉非IPV4地址
			tb = chk_ip4addr(tb)
			if next(tb) then
				for i,v in ipairs(tb) do
					str = str .. v .. "\n"
				end
				if fd then
					fd:write(str)
					fd:close()
				end
			else
				if fd then fd:close() end
			end
		else
			if fd then fd:close() end
		end
		m.uci:commit("nac")
	end
	-- 终端MAC
	srcmac = s:taboption(tname, Value, "b_mac", translate("Source MAC address List"),translate("Each line of a MAC, the format is 00:00:00:00:00:00"))
	srcmac.template = "cbi/tvalue"
	srcmac.rows = 5
	function srcmac.cfgvalue(self, section)
		local fd = io.open("/etc/config/freemac", "r")
		local str = ""
		if fd then
			str = fd:read("*a")
			fd:close()
		else
			fd = io.open("/etc/config/freemac", "w")
			if fd then
				fd:close()
				fd = io.open("/etc/config/freemac", "r")
				if fd then
					str = fd:read("*a")
					fd:close()
				end
			end
		end
		return str
	end
	function srcmac.write(self, section, value)
		--替换换行为\n
		value = value:gsub("\r\n?", "\n")
		local tb
		--移除所有空格
		tb=trim(value)
		local fd = io.open("/etc/config/freemac", "w")
		if string.len(tb) > 0 then
			local str = ""
			tb = rsplit(value,"\n")
			if next(tb) then
				for i,v in ipairs(tb) do
					str = str .. v .. "\n"
				end
				if fd then
					fd:write(str)
					fd:close()
				end
			else
				if fd then fd:close() end
			end
		else
			if fd then fd:close() end
		end
		m.uci:commit("nac")
	end
	-- 内网IP网段
	netsgt = s:taboption(tname,Value, "freeip_ns",translate("Source IP-Network List"),translate("Each line of a IP network, such as 101.226.0.0/16"))
	netsgt.template = "cbi/tvalue"

	netsgt.rows = 5
	function netsgt.cfgvalue(self, section)
		local fd = io.open("/etc/config/freeip_ns", "r")
		local str = ""
		if fd then
			str = fd:read("*a")
			fd:close()
		else
			fd = io.open("/etc/config/freeip_ns", "w")
			if fd then
				fd:close()
				fd = io.open("/etc/config/freeip_ns", "r")
				if fd then
					str = fd:read("*a")
					fd:close()
				end
			end
		end
		return str
	end
	function netsgt.write(self, section, value)
		--替换换行为\n
		value = value:gsub("\r\n?", "\n")
		local tb
		local tmp_tb = {}
		--移除所有空格
		tb=trim(value)
		local fd = io.open("/etc/config/freeip_ns", "w")
		if string.len(tb) > 0 then
			local str = ""
			tb = rsplit(value,"\n")
			for i,v in ipairs(tb) do
				local tmp = rsplit(v, "/")
				if luci.ip.IPv4(tmp[1]) and tmp[2] then
					if 0 < tonumber(tmp[2]) and 33 > tonumber(tmp[2]) then
						table.insert(tmp_tb, v)
					end
				end
			end
			if next(tmp_tb) then
				for i,v in ipairs(tmp_tb) do
					str = str .. v .. "\n"
				end
				if fd then
					fd:write(str)
					fd:close()
				end
			else
				if fd then fd:close() end
			end
		else
			if fd then fd:close() end
		end
		m.uci:commit("nac")
	end

end







m = Map("nac", translate("NAC"),
	translate("NAC is Network access control"))
m.redirect = ds.build_url("admin/ac_nac/nac")  

-- TypedSection表示以section的type来取得section指针
s = m:section(TypedSection, "base")
-- 不显示section的name
s.anonymous = true

-- section的tab
s:tab("general",  translate("Basic Settings"))
s:tab("portal",  translate("Portal Settings"))
s:tab("macauth", translate("MAC List"))
s:tab("radius",  translate("Authentication Settings"))
s:tab("destination", translate("Destination white"))
s:tab("source", translate("Source address white"))

-- @section nac.base
-- tab标签内的每一个option
o =s:taboption("general", ListValue, "net_mode", translate("Network interface mode"))
o.default = 1
o:value(1, translate("Bridge mode"))
o:value(2, translate("Routing mode"))
o:value(3, translate("NAT mode"))

if m.uci:get("nac","NAC","freeall")=="0" then
o = s:taboption("general", Value, "interface", translate("Wan interface"))
o:depends("net_mode", 1)
o.template    = "nac/nac_ifacelist"
o.widget      = "checkbox"
o.nocreate    = true
o.nobridges   = false
--o.rmempty     = false
o.noinactive = false
function o.write(self, s, value)
        local str = ""
        if value ~= nil then
                if type(value) == "string" then
                        str = str .. value
                elseif type(value) == "table" then
                        for i,v in ipairs(value) do
                        str = str .. v .. " "
                        end
                end
                m.uci:set("nac","NAC","interface", str)
       
        end
end


o = s:taboption("general", Value, "intercept", translate("Lan interface"))
o.template    = "nac/nac_ifacelist"
o.widget      = "checkbox"
o.nocreate    = true
o.nobridges   = false
o.rmempty     = false
o.noinactive = false
function o.write(self, s, value)
        local str = ""
        if value ~= nil then
                if type(value) == "string" then
                        str = str .. value
                elseif type(value) == "table" then
                        for i,v in ipairs(value) do
                        str = str .. v .. " "
                        end
                end
                m.uci:set("nac","NAC","intercept", str)
        end

end
end

o=s:taboption("general", Value, "nas", translate("NASIP"), translate("Fill in the external IP address"))
o.datatype = "ip4addr"
o:depends("freeall", "0")
function o.write(self, s, value)
       m.uci:set("nac","NAC","nas", value)
       m.uci:set("nac", "portal_cfg", "https_ip", value)
end


	o=s:taboption("general", ListValue, "r_mac_auth", translate("MAC authentic enable"))                                                                                                          
	o.default = 0               
	o:depends("freeall", "0")
	o:value(1, translate("Enable Some MAC"))                                                                                                                                  
	o:value(0, translate("off")) 
	o:value(2, translate("Enable All MAC")) 
        function o.cfgvalue(...)                                                                                                                                                               
                return m.uci:get("nac", "radius_cfg", "mac_auth")                                                                                                                                
        end                                                                                                                                                                                    
        function o.write(self, section, value)                                                                                                                                                 
                m.uci:set("nac", "radius_cfg", "mac_auth", value)                                                                                                                                
        end



o=s:taboption("general", ListValue, "freeall", translate("Auth Free"))
o.default = "1"
o:value("1", translate("Enabled"))
o:value("0", translate("Disabled"))

--[[
o=s:taboption("general", ListValue, "ip_conflict", translate("IP collision detection"), translate("When the terminal of the IP conflict, the first authentication of the terminal can normally access the network, after the authentication of the terminal can not play portal, can not be certified"))
o.default = "close"
o:value("open", translate("on"))
o:value("close", translate("off"))

]]--






-- 渲染portal数据
if m.uci:get("nac","NAC","freeall")=="0"  then
render_portal(s, "portal")
end
-- 渲染raidus数据
if m.uci:get("nac","NAC","freeall")=="0"  then
render_radius(s, "radius")
end
-- 渲染macauth数据
if m.uci:get("nac", "radius_cfg", "mac_auth") == "1" then
render_macauth(s, "macauth")
end
-- 渲染 bypass 外网白名单
if m.uci:get("nac","NAC","freeall")=="0"  then
render_bypass_outer_free(s, "destination")
-- 渲染 bypass 内网白名单
render_bypass_inter_free(s,"source")
end
function nac_action(srv)
	luci.sys.call("/etc/init.d/nac stop >/dev/null")
	if srv == "restart" then
		luci.sys.call("/etc/init.d/nac start >/dev/null")
		luci.sys.exec("lua /sbin/nasipchange.lua")
		luci.http.redirect(m.redirect)
	end
end

function m.on_after_commit(map)
	
	--local form_srv_enabled = luci.http.formvalue("cbid.wifidog.service.enabled")
	local apply = luci.http.formvalue("cbi.apply")
	if apply then
		nac_action("restart");
	else
		nac_action("");
	end
end 


return m
